package ac.il.technion.cs236635.project.core;

import java.io.Serializable;
import java.net.MalformedURLException;
import java.net.URL;

import javax.xml.namespace.QName;

import ac.il.technion.cs236635.project.core.client.ResultListener;
import ac.il.technion.cs236635.project.core.client.ResultListenerService;

public class ServerJob implements Runnable, Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 6931951458111630590L;

	private final static int DEFAULT_DELAY = 2000;
	
	private int jobId;
	
	private String clientName;
	
	private String clientEndpoint;
	
	private int delayInterval = 0;
	
	private StopListener listener = null;
	
	private boolean preemted = false;
	
	private boolean finished = false;

	private JobType jobType = JobType.LOW_PRIORITY;
	
	//private Logger log = Logger.getLogger( ServerJob.class);

	private RejectListener rejectListener = null;
	
	private long startTime = 0;

	private QName clientQName = new QName("http://core.project.cs236635.technion.il.ac/", "ResultListenerService");
	
	public long getStartTime() {
		return startTime;
	}

	public void setStartTime(long startTime) {
		this.startTime = startTime;
	}

	private long executionTime = 0;
	
	public ServerJob( ) {
		
	}
	
	public JobType getJobType() {
		return jobType;
	}

	public void setJobType(JobType jobType) {
		this.jobType = jobType;
	}

	public ServerJob( int delayInterval) {
		this.delayInterval = delayInterval;
	}
	
	public ServerJob( int id, final String clientName, final String clientEndpoint) {
		this( DEFAULT_DELAY);
		this.jobId = id;
		this.clientName = clientName;
		this.clientEndpoint = clientEndpoint;
	}
	
	public ServerJob( final String clientName, final String clientEndpoint) {
		this( DEFAULT_DELAY);
		this.clientName = clientName;
		this.clientEndpoint = clientEndpoint;
	}
	
	@Override
	public void run() {
		int delay = ( jobType == JobType.HIGH_PRIORITY)?delayInterval: delayInterval + 500;
		if ( jobType == JobType.HIGH_PRIORITY && listener != null)
			listener.notifyStopped( this);
		while( delay != 0 ) {
			if ( preemted)
				return;
			try {
				Thread.sleep( 100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			delay -= 100;
		}
		try {
			if ( FinishedJobsRegistration.getInstance().isJobFinished( jobId))
				return;
			ResultListenerService service = new ResultListenerService( new URL( clientEndpoint), clientQName);
			ResultListener resultListener = service.getResultListenerPort( );
			resultListener.jobIsReady( this);
			executionTime = System.currentTimeMillis() - startTime;
			FinishedJobsRegistration.getInstance().markFinished( this.getJobId( ));
			//log.info( "Job: " + jobId + " finished execution. Executed during (" + executionTime + ")");
		} catch (MalformedURLException e) {
			e.printStackTrace( );
		}
		if ( jobType == JobType.LOW_PRIORITY && listener != null)
			listener.notifyStopped( this);
		finished = true;
	}

	public boolean isFinished( ) {
		return finished;
	}
	
	public void preemtion( ) {
		preemted = true;
		//log.info( "Job: " + jobId + " has been preempted.");
		JobsQueue.getInstance().getStatistics().incPreemtedCount( );
	}
	
	public boolean isPreemted( ) {
		return preemted;
	}
	
	public int getJobId() {
		return jobId;
	}

	public ServerJob setJobId(int jobId) {
		this.jobId = jobId;
		return this;
	}

	public String getClientName() {
		return clientName;
	}

	public ServerJob setClientName(String clientName) {
		this.clientName = clientName;
		return this;
	}

	public String getClientEndpoint() {
		return clientEndpoint;
	}

	public ServerJob setClientEndpoint(String clientEndpoint) {
		this.clientEndpoint = clientEndpoint;
		return this;
	}

	public ServerJob addStopListener( final StopListener listener) {
		this.listener = listener;
		return this;
	}

	public ServerJob addRejectListener( final RejectListener listener) {
		this.rejectListener = listener;
		return this;
	}
	
	public RejectListener getRejectListener() {
		return rejectListener;
	}
}
